home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / debian_bundle / debfile.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  11.4 KB  |  270 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import gzip
  5. import string
  6. import tarfile
  7. import zlib
  8. from arfile import ArFile, ArError
  9. from changelog import Changelog
  10. from deb822 import Deb822
  11. DATA_PART = 'data.tar'
  12. CTRL_PART = 'control.tar'
  13. PART_EXTS = [
  14.     'gz',
  15.     'bz2']
  16. INFO_PART = 'debian-binary'
  17. MAINT_SCRIPTS = [
  18.     'preinst',
  19.     'postinst',
  20.     'prerm',
  21.     'postrm',
  22.     'config']
  23. CONTROL_FILE = 'control'
  24. CHANGELOG_NATIVE = 'usr/share/doc/%s/changelog.gz'
  25. CHANGELOG_DEBIAN = 'usr/share/doc/%s/changelog.Debian.gz'
  26. MD5_FILE = 'md5sums'
  27.  
  28. class DebError(ArError):
  29.     pass
  30.  
  31.  
  32. class DebPart(object):
  33.     '''\'Part\' of a .deb binary package.
  34.     
  35.     A .deb package is considered as made of 2 parts: a \'data\' part
  36.     (corresponding to the \'data.tar.gz\' archive embedded in a .deb) and a
  37.     \'control\' part (the \'control.tar.gz\' archive). Each of them is represented
  38.     by an instance of this class. Each archive should be a compressed tar
  39.     archive; supported compression formats are: .tar.gz, .tar.bz2 .
  40.  
  41.     When referring to file members of the underlying .tar.gz archive, file
  42.     names can be specified in one of 3 formats "file", "./file", "/file". In
  43.     all cases the file is considered relative to the root of the archive. For
  44.     the control part the preferred mechanism is the first one (as in
  45.     deb.control.get_content(\'control\') ); for the data part the preferred
  46.     mechanism is the third one (as in deb.data.get_file(\'/etc/vim/vimrc\') ).
  47.     '''
  48.     
  49.     def __init__(self, member):
  50.         self._DebPart__member = member
  51.         self._DebPart__tgz = None
  52.  
  53.     
  54.     def tgz(self):
  55.         '''Return a TarFile object corresponding to this part of a .deb
  56.         package.
  57.         
  58.         Despite the name, this method gives access to various kind of
  59.         compressed tar archives, not only gzipped ones.
  60.         '''
  61.         if self._DebPart__tgz is None:
  62.             name = self._DebPart__member.name
  63.             if name.endswith('.gz'):
  64.                 gz = gzip.GzipFile(fileobj = self._DebPart__member, mode = 'r')
  65.                 self._DebPart__tgz = tarfile.TarFile(fileobj = gz, mode = 'r')
  66.             elif name.endswith('.bz2'):
  67.                 self._DebPart__tgz = tarfile.open(fileobj = self._DebPart__member, mode = 'r:bz2')
  68.             else:
  69.                 raise DebError("part '%s' has unexpected extension" % name)
  70.         name.endswith('.gz')
  71.         return self._DebPart__tgz
  72.  
  73.     
  74.     def __normalize_member(fname):
  75.         """ try (not so hard) to obtain a member file name in a form relative
  76.         to the .tar.gz root and with no heading '.' """
  77.         if fname.startswith('./'):
  78.             fname = fname[2:]
  79.         elif fname.startswith('/'):
  80.             fname = fname[1:]
  81.         
  82.         return fname
  83.  
  84.     __normalize_member = staticmethod(__normalize_member)
  85.     
  86.     def has_file(self, fname):
  87.         '''Check if this part contains a given file name.'''
  88.         fname = DebPart._DebPart__normalize_member(fname)
  89.         names = self.tgz().getnames()
  90.         if not './' + fname in names:
  91.             pass
  92.         return fname in names
  93.  
  94.     
  95.     def get_file(self, fname):
  96.         '''Return a file object corresponding to a given file name.'''
  97.         fname = DebPart._DebPart__normalize_member(fname)
  98.         
  99.         try:
  100.             return self.tgz().extractfile('./' + fname)
  101.         except KeyError:
  102.             return self.tgz().extractfile(fname)
  103.  
  104.  
  105.     
  106.     def get_content(self, fname):
  107.         '''Return the string content of a given file, or None (e.g. for
  108.         directories).'''
  109.         f = self.get_file(fname)
  110.         content = None
  111.         if f:
  112.             content = f.read()
  113.             f.close()
  114.         
  115.         return content
  116.  
  117.     
  118.     def __iter__(self):
  119.         return iter(self.tgz().getnames())
  120.  
  121.     
  122.     def __contains__(self, fname):
  123.         return self.has_file(fname)
  124.  
  125.     
  126.     def has_key(self, fname):
  127.         return self.has_file(fname)
  128.  
  129.     
  130.     def __getitem__(self, fname):
  131.         return self.get_content(fname)
  132.  
  133.  
  134.  
  135. class DebData(DebPart):
  136.     pass
  137.  
  138.  
  139. class DebControl(DebPart):
  140.     
  141.     def scripts(self):
  142.         ''' Return a dictionary of maintainer scripts (postinst, prerm, ...)
  143.         mapping script names to script text. '''
  144.         scripts = { }
  145.         for fname in MAINT_SCRIPTS:
  146.             if self.has_file(fname):
  147.                 scripts[fname] = self.get_content(fname)
  148.                 continue
  149.         
  150.         return scripts
  151.  
  152.     
  153.     def debcontrol(self):
  154.         """ Return the debian/control as a Deb822 (a Debian-specific dict-like
  155.         class) object.
  156.         
  157.         For a string representation of debian/control try
  158.         .get_content('control') """
  159.         return Deb822(self.get_content(CONTROL_FILE))
  160.  
  161.     
  162.     def md5sums(self):
  163.         """ Return a dictionary mapping filenames (of the data part) to
  164.         md5sums. Fails if the control part does not contain a 'md5sum' file.
  165.  
  166.         Keys of the returned dictionary are the left-hand side values of lines
  167.         in the md5sums member of control.tar.gz, usually file names relative to
  168.         the file system root (without heading '/' or './'). """
  169.         if not self.has_file(MD5_FILE):
  170.             raise DebError("'%s' file not found, can't list MD5 sums" % MD5_FILE)
  171.         self.has_file(MD5_FILE)
  172.         md5_file = self.get_file(MD5_FILE)
  173.         sums = { }
  174.         for line in md5_file.readlines():
  175.             (md5, fname) = line.rstrip('\r\n').split(None, 1)
  176.             sums[fname] = md5
  177.         
  178.         md5_file.close()
  179.         return sums
  180.  
  181.  
  182.  
  183. class DebFile(ArFile):
  184.     '''Representation of a .deb file (a Debian binary package)
  185.  
  186.     DebFile objects have the following (read-only) properties:
  187.         - version       debian .deb file format version (not related with the
  188.                         contained package version), 2.0 at the time of writing
  189.                         for all .deb packages in the Debian archive
  190.         - data          DebPart object corresponding to the data.tar.gz (or
  191.                         other compressed tar) archive contained in the .deb
  192.                         file
  193.         - control       DebPart object corresponding to the control.tar.gz (or
  194.                         other compressed tar) archive contained in the .deb
  195.                         file
  196.     '''
  197.     
  198.     def __init__(self, filename = None, mode = 'r', fileobj = None):
  199.         ArFile.__init__(self, filename, mode, fileobj)
  200.         actual_names = set(self.getnames())
  201.         
  202.         def compressed_part_name(basename):
  203.             candidates = [ '%s.%s' % (basename, ext) for ext in PART_EXTS ]
  204.             parts = actual_names.intersection(set(candidates))
  205.             if not parts:
  206.                 raise DebError('missing required part in given .deb (expected one of: %s)' % candidates)
  207.             parts
  208.             if len(parts) > 1:
  209.                 raise DebError('too many parts in given .deb (was looking for only one of: %s)' % candidates)
  210.             len(parts) > 1
  211.             return list(parts)[0]
  212.  
  213.         if INFO_PART not in actual_names:
  214.             raise DebError("missing required part in given .deb (expected: '%s')" % INFO_PART)
  215.         INFO_PART not in actual_names
  216.         self._DebFile__parts = { }
  217.         self._DebFile__parts[CTRL_PART] = DebControl(self.getmember(compressed_part_name(CTRL_PART)))
  218.         self._DebFile__parts[DATA_PART] = DebData(self.getmember(compressed_part_name(DATA_PART)))
  219.         self._DebFile__pkgname = None
  220.         f = self.getmember(INFO_PART)
  221.         self._DebFile__version = f.read().strip()
  222.         f.close()
  223.  
  224.     
  225.     def __updatePkgName(self):
  226.         self._DebFile__pkgname = self.debcontrol()['package']
  227.  
  228.     version = property((lambda self: self._DebFile__version))
  229.     data = property((lambda self: self._DebFile__parts[DATA_PART]))
  230.     control = property((lambda self: self._DebFile__parts[CTRL_PART]))
  231.     
  232.     def debcontrol(self):
  233.         ''' See .control.debcontrol() '''
  234.         return self.control.debcontrol()
  235.  
  236.     
  237.     def scripts(self):
  238.         ''' See .control.scripts() '''
  239.         return self.control.scripts()
  240.  
  241.     
  242.     def md5sums(self):
  243.         ''' See .control.md5sums() '''
  244.         return self.control.md5sums()
  245.  
  246.     
  247.     def changelog(self):
  248.         ''' Return a Changelog object for the changelog.Debian.gz of the
  249.         present .deb package. Return None if no changelog can be found. '''
  250.         if self._DebFile__pkgname is None:
  251.             self._DebFile__updatePkgName()
  252.         
  253.         for fname in [
  254.             CHANGELOG_DEBIAN % self._DebFile__pkgname,
  255.             CHANGELOG_NATIVE % self._DebFile__pkgname]:
  256.             if self.data.has_file(fname):
  257.                 gz = gzip.GzipFile(fileobj = self.data.get_file(fname))
  258.                 raw_changelog = gz.read()
  259.                 gz.close()
  260.                 return Changelog(raw_changelog)
  261.         
  262.  
  263.  
  264. if __name__ == '__main__':
  265.     import sys
  266.     deb = DebFile(filename = sys.argv[1])
  267.     tgz = deb.control.tgz()
  268.     print tgz.getmember('control')
  269.  
  270.